package cn.bingoo.handy;

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import org.hibernate.jdbc.util.BasicFormatterImpl;
import org.hibernate.jdbc.util.Formatter;

import cn.bingoo.swing.utils.Clipboards;

public class IbatisLogSqlFrame extends JFrame {
    private static final long serialVersionUID = -4258764023338129931L;
    private JPanel contentPane;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    IbatisLogSqlFrame frame = new IbatisLogSqlFrame();
                    frame.setVisible(true);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public IbatisLogSqlFrame() {
        setTitle("iBatis Log SQL");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 631, 430);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        GridBagLayout gbl_contentPane = new GridBagLayout();
        gbl_contentPane.columnWidths = new int[] { 0, 0 };
        gbl_contentPane.rowHeights = new int[] { 0, 0, 0, 0 };
        gbl_contentPane.columnWeights = new double[] { 1.0, Double.MIN_VALUE };
        gbl_contentPane.rowWeights = new double[] { 1.0, 0.0, 1.0, Double.MIN_VALUE };
        contentPane.setLayout(gbl_contentPane);

        JScrollPane scrollPane = new JScrollPane();
        GridBagConstraints gbc_scrollPane = new GridBagConstraints();
        gbc_scrollPane.fill = GridBagConstraints.BOTH;
        gbc_scrollPane.insets = new Insets(0, 0, 5, 0);
        gbc_scrollPane.gridx = 0;
        gbc_scrollPane.gridy = 0;
        contentPane.add(scrollPane, gbc_scrollPane);

        final JTextArea textSrc = new JTextArea();
        textSrc.addFocusListener(new FocusAdapter() {
            @Override
            public void focusGained(FocusEvent e) {
                textSrc.selectAll();
            }
        });
        textSrc.setText("23:03:44,639 DEBUG PreparedStatement:27 - {pstm-100001} Executing Statement:                       SELECT S.STAFF_ID,                    S.STAFF_CODE,                    S.PASSWD,                    S.STAFF_NAME,                    S.LINK_PHONE,                    S.EMAIL,                    S.ESS_STAFF_ID,                    S.INIT_PASSWORD_TAG,                    P.PROVINCE_NAME,                    S.MERCHANT_ID,                    M.PROVINCE_CODE,                    M.CHANNEL_ID,                    M.CHANNEL_TYPE,                    M.MERCHANT_NAME,                    M.CITY_CODE,                    M.MERCHANT_TYPE              FROM TF_M_STAFF S ,TF_F_MERCHANT M, TF_M_PROVINCE P              WHERE S.MERCHANT_ID = M.MERCHANT_ID              AND P.PROVINCE_CODE (+)= M.PROVINCE_CODE              AND S.STAFF_CODE = UPPER(?)              AND S.STAFF_STATUS = '1'                         \r\n23:03:44,639 DEBUG PreparedStatement:27 - {pstm-100001} Parameters: [1100000]");
        scrollPane.setViewportView(textSrc);

        JPanel panel = new JPanel();
        GridBagConstraints gbc_panel = new GridBagConstraints();
        gbc_panel.insets = new Insets(0, 0, 5, 0);
        gbc_panel.fill = GridBagConstraints.BOTH;
        gbc_panel.gridx = 0;
        gbc_panel.gridy = 1;
        contentPane.add(panel, gbc_panel);
        GridBagLayout gbl_panel = new GridBagLayout();
        gbl_panel.columnWidths = new int[] { 0, 0, 0, 0, 0, 0 };
        gbl_panel.rowHeights = new int[] { 0, 0 };
        gbl_panel.columnWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE };
        gbl_panel.rowWeights = new double[] { 0.0, Double.MIN_VALUE };
        panel.setLayout(gbl_panel);

        JButton btnAnalyse = new JButton("Analyse");

        GridBagConstraints gbc_btnAnalyse = new GridBagConstraints();
        gbc_btnAnalyse.insets = new Insets(0, 0, 0, 5);
        gbc_btnAnalyse.gridx = 0;
        gbc_btnAnalyse.gridy = 0;
        panel.add(btnAnalyse, gbc_btnAnalyse);

        JButton btnCopy = new JButton("Copy");

        GridBagConstraints gbc_btnCopy = new GridBagConstraints();
        gbc_btnCopy.insets = new Insets(0, 0, 0, 5);
        gbc_btnCopy.gridx = 1;
        gbc_btnCopy.gridy = 0;
        panel.add(btnCopy, gbc_btnCopy);

        final JCheckBox chckbxSourceLinewrap = new JCheckBox("Source LineWrap");
        GridBagConstraints gbc_chckbxSourceLinewrap = new GridBagConstraints();
        gbc_chckbxSourceLinewrap.insets = new Insets(0, 0, 0, 5);
        gbc_chckbxSourceLinewrap.gridx = 2;
        gbc_chckbxSourceLinewrap.gridy = 0;
        panel.add(chckbxSourceLinewrap, gbc_chckbxSourceLinewrap);

        final JCheckBox chckbxResultLinewrap = new JCheckBox("Result LineWrap");

        chckbxResultLinewrap.setSelected(true);
        GridBagConstraints gbc_chckbxResultLinewrap = new GridBagConstraints();
        gbc_chckbxResultLinewrap.insets = new Insets(0, 0, 0, 5);
        gbc_chckbxResultLinewrap.gridx = 3;
        gbc_chckbxResultLinewrap.gridy = 0;
        panel.add(chckbxResultLinewrap, gbc_chckbxResultLinewrap);

        JButton btnBeautify = new JButton("Beautify");

        GridBagConstraints gbc_btnBeautify = new GridBagConstraints();
        gbc_btnBeautify.gridx = 4;
        gbc_btnBeautify.gridy = 0;
        panel.add(btnBeautify, gbc_btnBeautify);

        JScrollPane scrollPane_1 = new JScrollPane();
        GridBagConstraints gbc_scrollPane_1 = new GridBagConstraints();
        gbc_scrollPane_1.fill = GridBagConstraints.BOTH;
        gbc_scrollPane_1.gridx = 0;
        gbc_scrollPane_1.gridy = 2;
        contentPane.add(scrollPane_1, gbc_scrollPane_1);

        final JTextArea textResult = new JTextArea();
        scrollPane_1.setViewportView(textResult);
        textSrc.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void changedUpdate(DocumentEvent evt) {
                update();
            }

            @Override
            public void insertUpdate(DocumentEvent evt) {
                update();
            }

            @Override
            public void removeUpdate(DocumentEvent evt) {
                update();
            }

            private void update() {
                analyseSql(textSrc, textResult);
            }
        });

        btnAnalyse.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                analyseSql(textSrc, textResult);
            }
        });
        textSrc.setLineWrap(chckbxSourceLinewrap.isSelected());
        textResult.setLineWrap(chckbxResultLinewrap.isSelected());
        chckbxSourceLinewrap.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                textSrc.setLineWrap(chckbxSourceLinewrap.isSelected());
            }
        });
        chckbxResultLinewrap.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                textResult.setLineWrap(chckbxResultLinewrap.isSelected());
            }
        });
        btnCopy.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Clipboards.setClipboard(textResult.getText());
            }
        });
        btnBeautify.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Formatter f = new BasicFormatterImpl();
                String formatted_sql_code = f.format(textResult.getText());
                String lines[] = formatted_sql_code.split("\\r?\\n");
                StringBuilder sb = new StringBuilder();
                String indent = "";
                for (String line : lines) {
                    if (line.trim().length() > 0) {
                        String trimFirstLine = line.trim();
                        int pos = line.indexOf(trimFirstLine);
                        indent = line.substring(0, pos);
                        break;
                    }

                }
                if (indent.length() > 0) {
                    for (String line : lines) {
                        if (line.trim().length() == 0) {
                            continue;
                        }
                        int indexOf = line.indexOf(indent);
                        if (indexOf == 0) {
                            sb.append(line.substring(indent.length()));
                        }
                        else {
                            sb.append(line);
                        }
                        sb.append("\r\n");
                    }
                }

                textResult.setText(sb.toString());
            }
        });
    }

    private void analyseSql(final JTextArea textSrc, final JTextArea textResult) {
        String src = textSrc.getText();
        String[] lines = src.split("\n");
        for (int i = 0; i < lines.length; ++i) {
            int tagPos = lines[i].indexOf("Executing Statement:");
            if (tagPos >= 0) {
                String sql = lines[i].substring(tagPos + "Executing Statement:".length());
                sql = sql.trim();
                sql = sql.replaceAll("\\s+", " ");
                if (i + 1 < lines.length) {
                    String paramsLine = lines[i + 1];
                    int paramPos = paramsLine.indexOf("Parameters:");
                    if (paramPos >= 0) {
                        String params = paramsLine.substring(paramPos + "Parameters:".length());
                        params = params.trim();
                        if (params.charAt(0) == '[') {
                            params = params.substring(1);
                        }
                        if (params.charAt(params.length() - 1) == ']') {
                            params = params.substring(0, params.length() - 1);
                        }
                        String[] paramsArray = params.split(", ");
                        for (String param : paramsArray) {
                            sql = sql.replaceFirst("\\?", '\'' + param + '\'');
                        }

                        textResult.setText(sql);
                    }
                }
                break;
            }
        }
    }

}
